package org.artifact.core.plugin.rpc.server;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;
import org.artifact.core.plugin.ioc.IocPlugin;
import org.artifact.core.plugin.rpc.pojo.RpcRequest;
import org.artifact.core.plugin.rpc.pojo.RpcResponse;
import org.artifact.core.server.ServerPlugins;

import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutorService;

/**
 * RPC 服务端处理器（用于处理 RPC 请求）
 *
 * @author huangyong
 * @since 1.0.0
 */
public class RpcServerHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Log log = LogFactory.get(RpcServerHandler.class);


    ExecutorService executorService = ThreadUtil.newExecutor(8);

    ExecutorService single = ThreadUtil.newSingleExecutor();

    @Override
    public void channelRead0(final ChannelHandlerContext ctx, RpcRequest request) throws Exception {
        executorService.submit(() -> {
                    // 创建并初始化 RPC 响应对象
                    RpcResponse response = new RpcResponse();
                    response.setRequestId(request.getRequestId());
                    try {
                        Object result = handle(request);
                        response.setResult(result);
                    } catch (InvocationTargetException e) {
                        Throwable throwable = ExceptionUtil.unwrap(e);
                        log.error(throwable);
                        response.setException(throwable);
                    } catch (Exception e) {
                        log.error("handle result failure", e);
                        response.setException(e);
                    }
//                    single.submit(() -> ctx.writeAndFlush(response));
                    ctx.writeAndFlush(response);
                }
        );
    }

    private Object handle(RpcRequest request) throws Exception {

        // 获取服务对象
        String serviceName = request.getInterfaceName();
        String serviceVersion = request.getServiceVersion();
//        if (StrUtil.isNotEmpty(serviceVersion)) {
//            serviceName += "-" + serviceVersion;
//        }
        IocPlugin iocPlugin = ServerPlugins.me().getPlugin(IocPlugin.class);
        Object serviceBean = iocPlugin.getService(serviceName);
        if (serviceBean == null) {
//            iocPlugin.showIOC();
            throw new RuntimeException(String.format("can not find service bean by key: %s", serviceName));
        }
        // 获取反射调用所需的参数
        Class<?> serviceClass = serviceBean.getClass();
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();
        // 执行反射调用
//        Method method = serviceClass.getMethod(methodName, parameterTypes);
//        method.setAccessible(true);
//        return method.invoke(serviceBean, parameters);
        // 使用 CGLib 执行反射调用
        FastClass serviceFastClass = FastClass.create(serviceClass);
        FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);
        return serviceFastMethod.invoke(serviceBean, parameters);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("server caught exception", cause);
        ctx.close();
    }
}
